#ifndef __COMPAT_OBJECT_INTERFACE_H__
#define __COMPAT_OBJECT_INTERFACE_H__

/*!
 *	\file	object.h
 *	\class	object
 *	\author	ownrisk@gmail.com
 *	\desc	...
 */

#include "placeholder.h"
#include "type_traits.h"

class object
{
public:
	template < typename value_type >
	object ( const value_type & value ) ;
	object ( const object & other ) ;

	object ( void ) ;
	~object ( void ) ;

public:
	template < typename value_type >
	object & operator = ( const value_type & rhs ) ;
	object & operator = ( const object & rhs ) ;

public: 
	object &				swap ( object & rhs ) ;
	bool					empty ( void ) const ;
	const std::type_info &	type ( void ) const ;

private:
	placeholder *			placeholder_ ;	// real data

	template < typename value_type >
	friend value_type *		type_cast ( object * ) ;	// friend method for access to 'placeholder_'
} ;



template < typename value_type >
object::object ( const value_type & value )
: placeholder_ ( new typeholder < value_type > ( value ) )
{

}


template < typename value_type >
object & object::operator = ( const value_type & rhs )
{
	object ( rhs ).swap ( *this ) ;	// safety destruction
	return *this;
}


template < typename value_type >
value_type * type_cast ( object * value )
{
	if ( value == NULL )	return NULL ;

	if ( value->type() == typeid ( void ) )
		throw std::bad_cast ("invalid type cast. source is void type") ;

	return &static_cast<typeholder<value_type> *>(value->placeholder_)->holder ;
}


template < typename value_type >
const value_type * type_cast ( const object * operand )
{
	return type_cast<value_type>(const_cast<object *>(operand)) ;
}



template < typename value_type >
value_type type_cast ( const object & value )
{
	typedef typename remove_reference<value_type>::type deref_type ;

	const deref_type * ptr = type_cast<deref_type> ( &value );
	if ( ptr == NULL )
		throw std::bad_cast ("wrong type cast") ;

	return *ptr;
}


template < typename value_type >
value_type type_cast ( object & value )
{
	typedef typename remove_reference<value_type>::type	deref_type ;

	deref_type * ptr = type_cast<deref_type> ( &value );
	if ( ptr == NULL )
		throw std::bad_cast ("wrong type cast") ;

	return *ptr;
}


//template < typename dst_type, typename src_type >
//dst_type type_cast ( const src_type & operand )
//{
//	return static_cast<dst_type> ( operand ) ;
//}


	//template < typename value_type >
	//bool	operator == ( const value_type & rhs ) const ;
	//bool	operator == ( const object & rhs ) const ;

	//template < typename value_type >
	//bool	operator != ( const value_type & rhs ) const ;
	//bool	operator != ( const object & rhs ) const ;

	//template < typename value_type >
	//bool	operator < ( const value_type & rhs ) const ;
	//bool	operator < ( const object & rhs ) const ;

	//template < typename value_type >
	//bool	operator <= ( const value_type & rhs ) const ;
	//bool	operator <= ( const object & rhs ) const ;

	//template < typename value_type >
	//bool	operator > ( const value_type & rhs ) const ;
	//bool	operator > ( const object & rhs ) const ;

	//template < typename value_type >
	//bool	operator >= ( const value_type & rhs ) const ;
	//bool	operator >= ( const object & rhs ) const ;

//template < typename value_type >
//bool object::operator == ( const value_type & rhs ) const
//{
//	return true ;
//}
//
//
//template < typename value_type >
//bool object::operator != ( const value_type & rhs ) const
//{
//	return true ;
//}
//
//
//template < typename value_type >
//bool object::operator < ( const value_type & rhs ) const
//{
//	return true ;
//}
//
//
//template < typename value_type >
//bool object::operator <= ( const value_type & rhs ) const
//{
//	return true ;
//}
//
//
//template < typename value_type >
//bool object::operator > ( const value_type & rhs ) const
//{
//	return true ;
//}
//
//
//template < typename value_type >
//bool object::operator >= ( const value_type & rhs ) const
//{
//	return true ;
//}


#endif	// #ifndef __COMPAT_OBJECT_INTERFACE_H__